import socket
import threading
import tkinter as tk
import sys     
import time
class Client:
    #目的服务器的ip地址
    serverIp = ''
    #目的服务器套接字的端口号
    serverPort = 12000 
    lock = threading.Lock()
    #创建客户的TCP套接字
    cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #输入信息
    sendmessage = ''
    #接收信息
    recvMessage = ''
    #标志是否有信息发送
    sendflag = False
    #标志是否有接收信息
    recvflag = False
    #主线程
    def main(self):
        try:
            self.cs.connect((self.serverIp, self.serverPort))
            self.recvMessage = '已连接到服务器'
            self.recvflag = True
        except:
            self.recvMessage = '因目的主机不在线或ip地址无效,程序即将关闭'
            print(self.recvMessage)
            self.recvflag = True
        #开启线程阻塞接收服务器的信息
        self.server_thread = threading.Thread(target = self.handle_socket)
        self.server_thread.start()
        #开启线程监听要发送的信息
        self.client_main = threading.Thread(target = self.handle_send)
        self.client_main.start()
    def handle_send(self):
        while True:
            if(self.sendflag):
                self.lock.acquire()
                self.cs.send(self.sendmessage.encode())
                self.lock.release()
                self.sendflag = False
                time.sleep(0.1)
    def handle_socket(self):
        while True:
            try:
                self.recvMessage = self.cs.recv(1024)
            except:
                break
            self.recvMessage = self.recvMessage.decode()
            if self.recvMessage == '\0': #判断是否是服务器的状态查询信息
                self.lock.acquire()
                self.cs.send('\0'.encode())
                self.lock.release()
            else:
                self.recvflag = True
class GUI:
    client = Client()
    root = tk.Tk()
    root.title("your father")
    #文本框矩形
    frame1 = tk.Frame(root,bd = 30)
    #文本显示框
    text1 = tk.Entry(frame1, bd = 5, width = 30)
    #消息显示框矩形
    frame2 = tk.Frame(root,bd = 80,bg = 'pink')
    #接收ip地址矩形
    frame3 = tk.Frame(root, bd = 10)
    label1 = tk.Label(frame3,text = '在这输入服务器主机名或ip地址')
    text2 = tk.Entry(frame3, bd = 3, width = 20) #接受IP地址
    #消息显示框
    sb = tk.Scrollbar(frame2)
    news = tk.Listbox(frame2,yscrollcommand=sb.set,width = 80, height = 26)
    def __init__(self):
        #接收ip地址矩形
        self.label1.pack(anchor = 'w', side = 'top')
        self.text2.pack(anchor = 'w', side = 'left')
        self.button1 = tk.Button(self.frame3, text = 'submit',command = self.changeip_run)
        self.button1.pack(anchor = 'e',side = 'right')
        
        self.text1.xview_scroll(number = 1, what = tk.UNITS )#水平滚动
        self.text1.pack(anchor = 'w', side = 'left')
        self.hi_there = tk.Button(self.frame1,text="submit~",command = self.say_hi)
        self.hi_there.pack(anchor = 'e', side = 'right')
        self.sb.pack(side=tk.RIGHT,fill=tk.Y)
        self.news.pack(side = 'top',fill=tk.BOTH)
        self.sb.config(command=self.news.yview)
        self.frame3.pack()
        self.frame2.pack()
        self.frame1.pack()
    #接受了用户输入的ip地址，开始建立连接
    def changeip_run(self):
        self.button1.config(state=tk.DISABLED) #按钮不可点击
        self.client.serverIp = str(self.text2.get())
        self.start_monitor()
        self.client.main() #启动底层线程
    def start_monitor(self):
        self.server_thread = threading.Thread(target = self.monitor_recv)
        self.server_thread.start()
    def say_hi(self):
        self.client.sendmessage = str(self.text1.get())
        self.client.sendflag = True #命令开始向套接字发送
        self.text1.delete(0, tk.END)  # 删除所有值
    def monitor_recv(self):
        while True:
            if self.client.recvflag:
                self.news.insert(tk.END,self.client.recvMessage)
                self.client.recvflag = False
                if self.client.recvMessage == '因目的主机不在线或ip地址无效,程序即将关闭':
                    time.sleep(3)
                    self.root.destroy()
                    self.client.cs.close()
                    sys.exit()
                
if __name__ == '__main__':
    gui = GUI()
    gui.root.mainloop()
    gui.client.cs.close()
    sys.exit()



